<?php
namespace StarCloud\Services\Export;

use StarCloud\Library\Exception;
use StarCloud\Services\BaseService;

/**
 * @author      : fengshuang@zuoyebang.com
 * @date        : 2020-10-04 10:49
 * @description : 导出的基类
 */
abstract class BaseExport extends BaseService implements InterfacteExport
{
    protected $exportMaxRows = 2000;

    protected $_isExport = false;
    private $filename = '';
    private $hasSetFileHeader = false;
    protected $hasSetFileName = true;
    protected $max_count = 10000;

    protected $arrOutput = [];

    public function __construct()
    {
    }

    /**
     * @param array $arrInput 输入参数
     * @param bool $isExport 是否是导出, 不是导出就是列表
     * @return array
     */
    public function execute(array $arrInput, bool $isExport = false)
    {
        $this->_isExport = $isExport;
        // 分页和导出的区别就在于, 分页是一页, 导出是全部. 其实可以用导出来调用分页, 从而用一个类实现全部功能
        if ($isExport) {
            $arrInput['page'] = 1;
            $arrInput['count'] = $this->exportMaxRows;
            $this->setFile();

            // 这里的参数需要处理一下
            if (!empty($arrInput['taskParams']) && is_array($arrInput['taskParams'])) {
                $arrParams = array_merge($arrInput, $arrInput['taskParams']);
            } else {
                $arrParams = $arrInput;
            }

            $arrInput = $arrParams;
            // 导出
            do {
                // 列表
                $this->invoke($arrInput);

                if ($this->arrOutput['total_number'] > $this->max_count) {
                    throw new Exception(10019);
                }

                $this->writeFileName();

                $this->writeFileHeader();

                $this->appendToFile();

                $arrInput['page']++;
            } while ($this->arrOutput['next'] > 0);
        } else {
            // 列表
            $this->invoke($arrInput);
        }

        return $this->arrOutput;
    }

    abstract protected function invoke(array $arrInput);

    protected function setFile()
    {
        $this->filename = sprintf(ROOT_PATH . "/static/export/export_%d.csv", time());
        if (file_exists($this->filename)) {
            unlink($this->filename);
        }
        touch($this->filename);
    }

    protected function writeFileHeader()
    {
        if (!$this->hasSetFileHeader) {
            $header = $this->getFileHeader();
            if (is_array($header) && count($header)) {
                $this->hasSetFileHeader = true;
                $line = "";
                foreach ($header as $item) {
                    $line .= "," . iconv("UTF-8", "GB2312//IGNORE", $item);
                }
                $line = substr($line, 1);
                $line .= "\n";
                file_put_contents($this->filename, $line, FILE_APPEND);
            }
        }
    }

    protected function writeFileName()
    {
        if (!$this->hasSetFileName) {
            $name = $this->getFileName();
            if (is_string($name)) {
                $this->hasSetFileName = true;
                $line = iconv("UTF-8", "GB2312//IGNORE", $name);
                $line .= "\n";
                file_put_contents($this->filename, $line, FILE_APPEND);
            }
        }
    }

    public function getFile()
    {
        return $this->filename;
    }

    public function appendToFile()
    {
        $file = fopen($this->filename, "a");
        foreach ($this->arrOutput['data'] as $k => $item) {
            if (method_exists($this, "lineMap")) {
                $line = $this->lineMap($item);
            } else {
                $line = $item;
            }
            fputcsv($file, $line);
        }
    }

    public function convertToGB2312($arr)
    {
        $lineItem = [];
        foreach ($arr as $item) {
            $item = str_replace(',', ';', $item);
            $lineItem[] = iconv("UTF-8", "GB2312//IGNORE", $item);
        }

        return $lineItem;
    }

    /**
     * CSV的文件头
     */
    public function getFileHeader()
    {
        return [];
    }

    /**
     * CSV的文件头
     */
    public function getFileName()
    {
        return [];
    }
}
